feat(cli): meta init scaffolds owned codegen generators (ADR-0034)#87
Merged
Conversation
…p 2)
Stop wiring the scaffolded config to the package's black-box generator export.
`meta init` now copies the four copyable reference templates
(codegen-ts/src/reference/{entity,queries,routes,barrel}.ts) into the consumer
repo at codegen/generators/*.ts and points metaobjects.config.ts at those LOCAL
copies — so `meta gen` runs from generators the consumer owns and can edit
(the shadcn-for-codegen model).
- codegen-ts: new reference-templates.ts reader (resolveReferenceRoot /
readReferenceTemplate / REFERENCE_GENERATOR_NAMES), exported from the index.
The reference assets already ship via `files: ["src"]` (verified in the
packed tarball).
- cli init: writeOwnedGenerators() copies each template, write-only-if-absent so
--force never clobbers a hand-edited generator; the scaffolded config imports
./codegen/generators/*; printOnly + next-steps updated.
- Deprecate the @metaobjectsdev/codegen-ts/generators factory re-exports
(JSDoc @deprecated → scaffold-and-own path); not removed (pre-GA latitude,
drop in a later major).
Verified: a fresh `meta init` + `meta gen` in a temp dir emits working
Entity/queries/routes/barrel output entirely from the owned local generators;
byte-identical reference test still green.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LuZWKnWzYGVnESijL7uuky
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Intent
ADR-0034 codegen scaffold-and-own, step 2. Goal: stop wiring the scaffolded metaobjects.config.ts to the package's black-box generators export; instead have 'meta init' copy the four copyable reference templates (codegen-ts/src/reference/{entity,queries,routes,barrel}.ts, shipped by PR #86) into the consumer repo at codegen/generators/*.ts and import them LOCALLY, so 'meta gen' runs from generators the consumer owns and edits (the shadcn-for-codegen model). Decisions made: (1) write-only-if-absent when copying generators so re-running 'meta init --force' never clobbers a hand-edited generator (mirrors the existing config.ts preservation); (2) added a small reference-template reader to codegen-ts (resolveReferenceRoot/readReferenceTemplate/REFERENCE_GENERATOR_NAMES, exported from the index) — the CLI reads the templates through it; the reference assets already ship via the package's files:[src] entry; (3) DEPRECATE but do NOT remove the @metaobjectsdev/codegen-ts/generators factory re-exports (JSDoc @deprecated only — pre-GA latitude, removal deferred to a later major) per the locked design decision; (4) updated init-refresh-docs and init-scaffold-config tests to assert the new local-import wiring and added an owned-generators scaffold test + a codegen-ts reference-templates reader test. Verified manually: a fresh 'meta init' + 'meta gen' in a temp dir emits working entity/queries/routes/barrel output entirely from the owned local generators; the byte-identical reference test stays green. NOTE: this is a public repo; this is a shared checkout with a concurrent no-mistakes run on another branch (feat/codegen-friction-model-first) — leave that alone.
What Changed
meta initnow copies the four copyable reference templates (entity/queries/routes/barrel) into the consumer repo atcodegen/generators/*.tsand wires the scaffoldedmetaobjects.config.tsto import those owned local copies instead of the package's black-box@metaobjectsdev/codegen-ts/generatorsexport — the shadcn-for-codegen model. Copying is write-only-if-absent, so re-runningmeta init --forcenever clobbers a hand-edited generator.codegen-ts(resolveReferenceRoot/readReferenceTemplate/REFERENCE_GENERATOR_NAMES, exported from the index) that the CLI uses to read the bundledsrc/reference/*.tsassets; the@metaobjectsdev/codegen-ts/generatorsfactory re-exports are now JSDoc@deprecated(deprecated, not removed — removal deferred to a later major).init-refresh-docsandinit-scaffold-configtests to assert the local-import wiring, added an owned-generators scaffold test and areference-templatesreader test, and synced CHANGELOG/docs to describe the newmeta initbehavior.Risk Assessment
✅ Low: A small, well-bounded scaffold change that mirrors existing write-if-absent preservation patterns, is covered by new and updated tests, declares its new runtime dependency, and the dual-layout reference resolver correctly handles both dev (src) and published (dist+src) installs.
Testing
Ran the three change-targeted unit suites (all green individually) plus a faithful end-to-end CLI transcript that runs
meta init→meta gen→meta init --forceas an end user would. The transcript shows the four reference templates copied intocodegen/generators/with their REFERENCE TEMPLATE headers, the scaffoldedmetaobjects.config.tsimporting each generator locally (and never the deprecated package export), real generated Drizzle/Zod/Fastify/barrel output produced entirely from those owned local generators, and a hand-edited owned generator surviving--force. One setup fix was needed (rootbun installfor the jsdom test preload); the only quirk observed was that running the three target test files in a singlebun testinvocation hit a 2-minute wall on first-run package loading, so I ran them separately and each passed — this is a harness startup cost, not a failure of the change. The change is CLI/codegen scaffolding with no rendered UI surface, so a CLI transcript (not a screenshot) is the appropriate end-user evidence; saved at the path below. Worktree left clean.Evidence: meta init → meta gen → meta init --force end-to-end CLI transcript (owned generators, generated output, --force preservation)
Pipeline
Updates from git push no-mistakes
✅ **intent** - passed
✅ No issues found.
✅ **Rebase** - passed
✅ No issues found.
server/typescript/packages/codegen-ts/src/reference-templates.ts:31-meta initnow hard-fails if the codegen-tssrc/reference/*.tsassets can't be resolved (resolveReferenceRoot throws). This couples init's success — previously independent of codegen-ts file assets — to those assets shipping in the installed package. It's protected byfiles:["src"], so the practical risk is low, but a bundled or stripped install of @metaobjectsdev/codegen-ts would break a previously-workingmeta init, and writeOwnedGenerators runs before the config write so a throw leaves a half-scaffolded project.server/typescript/packages/cli/src/commands/init.ts:285- The printOnly (dry-run) branch unconditionally reports the four owned generators ascreated, but the real path reports them aspreservedwhen they already exist (e.g.meta init --force --printover an existing project). This mislabels preserved generators in the preview — though it matches the same already-imperfect convention used for config.json/meta.common.json in printOnly, so it's a pre-existing pattern rather than a new defect.server/typescript/packages/codegen-ts/src/reference-templates.ts:21- isReferenceRoot only checks forentity.ts; a partial/corrupt install with entity.ts present but missing queries/routes/barrel would pass the root check, then fail later inside readReferenceTemplate with a raw ENOENT rather than the helpful 'reference templates not found' message. Marginal robustness nit.✅ **Test** - passed
✅ No issues found.
bun test packages/cli/test/unit/init-scaffold-config.test.ts(9 pass) — owned-generators scaffold + local-import wiring + --force preservationbun test packages/cli/test/unit/init-refresh-docs.test.ts(9 pass) — config imports./codegen/generators/entity, never the package/generatorsexportbun test packages/codegen-ts/test/reference-templates.test.ts(3 pass) — resolveReferenceRoot/readReferenceTemplate/REFERENCE_GENERATOR_NAMES readerManual end-to-end: in a simulated consumer project (top-level node_modules symlinking@metaobjectsdev/{cli,codegen-ts,metadata}+ts-poet), ranmeta init→ copied owned generators + locally-wired config; authored aProductentity;meta gen(from project root) emitted working Drizzle/Zod entity, queries, Fastify routes, and barrel from the owned local generators (exit 0, 4 files);meta init --forceafter hand-editingentity.tspreserved the edit (write-only-if-absent)Setup fix:bun installat repo root to provide the jsdom test-preload dependencyagent-context/skills/metaobjects-codegen/references/typescript.md:35- The agent-facing guidance (agent-context/skills/metaobjects-codegen/references/typescript.md) still teaches importing entityFile/queriesFile/routesFile/barrel from the deprecated @metaobjectsdev/codegen-ts/generators export. I did not edit it: this file is byte-identical to four agent-context-conformance fixtures (a hard gate), and the 'guidance rewrite' is explicitly the separately-scoped ADR-0034 Phase-1 step (per the CHANGELOG step-1 note, distinct from this 'meta init + deprecation' step). Updating it requires coordinated regeneration of all four expected fixture sets.spec/decisions/ADR-0034-codegen-scaffold-and-own.md:57- ADR-0034 Decision 3 states in present tense that you 'cannot import { entityFile } from "@metaobjectsdev/codegen-ts/generators"' (force-by-removal). Step 2 instead deprecated (not removed) the export, the gentler path the ADR's own open question and the design doc resolve as 'deprecate one minor, then remove.' Left as-is since it represents the durable architectural target and the phasing is documented in the design doc; a human may want to soften the wording to 'will be removed' for accuracy.✅ **Lint** - passed
✅ No issues found.
✅ **Push** - passed
✅ No issues found.